{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "bd97020a",
   "metadata": {},
   "source": [
    "# Tutorial 3: Replicated Secret Sharing\n",
    "Replicated Secret Sharing is used to securely share secret information among three parties, and in the scenario of three-parties replication, there are usually three participants work together to store and manage secrets. The secret is divided into three parts by some algorithm, with each participant holding one part. The separate parts don't have enough information to recover the secret. When a secret needs to be used, at least two participants need to cooperate, combining the parts they hold to recover the original secret. Currently, our models and features are based on honest-majority designs. To use replicated secret sharing in secure three-party calculations, we import the following packages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "f265a5cc",
   "metadata": {},
   "outputs": [],
   "source": [
    "from NssMPC import RingTensor\n",
    "from NssMPC import ReplicatedSecretSharing\n",
    "from NssMPC.crypto.protocols.replicated_secret_sharing.honest_majority_functional.compare import secure_ge\n",
    "from NssMPC.secure_model.mpc_party import SemiHonest3PCParty, HonestMajorityParty\n",
    "from NssMPC.config.runtime import PartyRuntime\n",
    "\n",
    "import torch"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a61fb281",
   "metadata": {},
   "source": [
    "```RingTensor``` is the main data structure that we use.\n",
    "```HonestMajorityParty``` means participants in 3-party replicated secret sharing computation based on the honest majority model.\n",
    "```ReplicatedSecretSharing``` is a class for replicated secret sharing over a RingPair.\n",
    "```SemiHonest3PCParty``` is used for three parties to communicate with each other"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dbf1c2bc",
   "metadata": {},
   "source": [
    "## Party\n",
    "At least two parties are honest, meaning they will act according to the agreement and will not intentionally tamper with data or behavior. There may be a malicious party that tries to influence the outcome by providing incorrect information or tampering with data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "b1b74d22",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "TCPServer waiting for connection ......\n",
      "TCPServer waiting for connection ......\n",
      "TCPServer waiting for connection ......\n",
      "successfully connect to server 127.0.0.1:7000\n",
      "TCPServer successfully connected by :('127.0.0.1', 8100)\n",
      "successfully connect to server 127.0.0.1:9000\n",
      "TCPServer successfully connected by :('127.0.0.1', 8200)\n",
      "successfully connect to server 127.0.0.1:9000\n",
      "TCPServer successfully connected by :('127.0.0.1', 7100)\n",
      "successfully connect to server 127.0.0.1:8000\n",
      "TCPServer successfully connected by :('127.0.0.1', 7200)\n",
      "successfully connect to server 127.0.0.1:8000\n",
      "TCPServer successfully connected by :('127.0.0.1', 9100)\n",
      "successfully connect to server 127.0.0.1:7000\n",
      "TCPServer successfully connected by :('127.0.0.1', 9200)\n",
      "Server 1 is now online\n",
      "Server 2 is now online\n",
      "Server 0 is now online\n"
     ]
    }
   ],
   "source": [
    "import threading\n",
    "Party0 = HonestMajorityParty(id=0)\n",
    "Party1 = HonestMajorityParty(id=1)\n",
    "Party2 = HonestMajorityParty(id=2)\n",
    "# Set P0\n",
    "def set_P0():\n",
    "    with PartyRuntime(Party0):\n",
    "        Party0.set_comparison_provider()\n",
    "        # P0 connect\n",
    "        Party0.online()\n",
    "\n",
    "# Set P1\n",
    "def set_P1():\n",
    "    with PartyRuntime(Party1):\n",
    "        Party1.set_comparison_provider()\n",
    "        # P1 connect\n",
    "        Party1.online()\n",
    "\n",
    "# Set P2\n",
    "def set_P2():\n",
    "    with PartyRuntime(Party2):\n",
    "        Party2.set_comparison_provider()\n",
    "        # P2 connect\n",
    "        Party2.online()\n",
    "    \n",
    "p0_thread = threading.Thread(target=set_P0)\n",
    "p1_thread = threading.Thread(target=set_P1)\n",
    "p2_thread = threading.Thread(target=set_P2)\n",
    "\n",
    "p0_thread.start()\n",
    "p1_thread.start()\n",
    "p2_thread.start()\n",
    "p0_thread.join()\n",
    "p1_thread.join()\n",
    "p2_thread.join()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fb02b535",
   "metadata": {},
   "source": [
    "If you see three instances of \"successfully connected\" with two targets, it indicates that the communication between the three parties has been established successfully."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f5e20dc6",
   "metadata": {},
   "source": [
    "## Secret Sharing\n",
    "P0 will create 2 RingTensors( x and y）to test and use the ```share``` method from ```ReplicatedSecretSharing``` (RSS) to perform data sharing. Additionally, you need to utilize TCP to send party0's shares to another parties and receive their own shares."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "3a406087",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([1.1000, 1.1000, 1.3000])\n",
      "test_tensor:  RingTensor\n",
      " value:tensor([72090, 72090, 85197]) \n",
      " dtype:float \n",
      " scale:65536\n",
      "RingTensor\n",
      " value:tensor([72090, 72090, 85197]) \n",
      " dtype:float \n",
      " scale:65536\n",
      "RingTensor\n",
      " value:tensor([72090, 72090, 85197]) \n",
      " dtype:float \n",
      " scale:65536\n",
      "tensor([1.1000, 1.1000, 1.3000], dtype=torch.float64)\n"
     ]
    }
   ],
   "source": [
    "from NssMPC.crypto.protocols.replicated_secret_sharing.honest_majority_functional.compare import secure_ge\n",
    "from NssMPC.config.configs import DEVICE\n",
    "\n",
    "def p0_share():\n",
    "    with PartyRuntime(Party0):\n",
    "        x = torch.tensor([1.1, 1.1, 1.3], device=DEVICE)\n",
    "        y = torch.tensor([1.2, 1.1, 2.3], device=DEVICE)\n",
    "        print(x)\n",
    "        x = RingTensor.convert_to_ring(x)\n",
    "        y = RingTensor.convert_to_ring(y)\n",
    "        print(\"test_tensor: \", x)\n",
    "        shares_X = ReplicatedSecretSharing.share(x)\n",
    "        shares_Y = ReplicatedSecretSharing.share(y)\n",
    "    \n",
    "        Party0.send(1, shares_X[1])\n",
    "        Party0.send(2, shares_X[2])\n",
    "    \n",
    "        Party0.send(1, shares_Y[1])\n",
    "        Party0.send(2, shares_Y[2])\n",
    "    \n",
    "        shared_x = shares_X[0]\n",
    "        shared_y = shares_Y[0]\n",
    "        shared_x.party = Party0\n",
    "        shared_y.party = Party0\n",
    "        print(shared_x.restore().convert_to_real_field())\n",
    "    \n",
    "    \n",
    "    \n",
    "    \n",
    "def p1_share():\n",
    "    with PartyRuntime(Party1):\n",
    "        shared_x = Party1.receive(0)\n",
    "        shared_y = Party1.receive(0)\n",
    "        print(shared_x.restore())\n",
    "    \n",
    "\n",
    "    \n",
    "def p2_share():\n",
    "    with PartyRuntime(Party2):\n",
    "        shared_x = Party2.receive(0)\n",
    "        shared_y = Party2.receive(0)\n",
    "        print(shared_x.restore())\n",
    "    \n",
    "p0_thread = threading.Thread(target=p0_share)\n",
    "p1_thread = threading.Thread(target=p1_share)\n",
    "p2_thread = threading.Thread(target=p2_share)\n",
    "\n",
    "p0_thread.start()\n",
    "p1_thread.start()\n",
    "p2_thread.start()\n",
    "p0_thread.join()\n",
    "p1_thread.join()\n",
    "p2_thread.join()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d74b6b9d",
   "metadata": {},
   "source": [
    "####  Operations\n",
    "The operations in Replicated Secret Sharing are similiar to the operations in Arithmetic secret sharing."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.19"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
